package la.bbs558.util;

import cn.hutool.core.collection.ListUtil;
import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.util.List;
import java.util.concurrent.*;
import java.util.function.Consumer;

public class ExecutorManager {

    public static ExecutorService myExecutor;
    public static ExecutorService jmMsgExecutor;
    public static ExecutorService delayExecutor;

    static {
        myExecutor = myExecutor();
        jmMsgExecutor = jmMsgExecutor();
        delayExecutor = delayExecutor();
    }

    private static ExecutorService myExecutor() {
        return getThreadPoolExecutor(50000, "my-pool-%d", 10, 30);
    }

    private static ExecutorService jmMsgExecutor() {
        return getThreadPoolExecutor(1000, "jmMsg-pool-%d", 5, 10);
    }

    private static ExecutorService delayExecutor() {
        return getThreadPoolExecutor(5000, "delay-pool-%d", 5, 10);
    }

    public static <T> void  batchExecute(int threadNum,List<T> data, Consumer<T> consumer,ExecutorService executorService){
        List<List<T>> split = ListUtil.split(data, threadNum);
        for (List<T> ts : split) {
            executorService.execute(()->{
                for (T t : ts) {
                    consumer.accept(t);
                }
            });
        }
    }

    private static ThreadPoolExecutor getThreadPoolExecutor(int capacity, String nameFormat, int core, int max) {
        int cpuNum = Runtime.getRuntime().availableProcessors();
        BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(capacity);
        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat(nameFormat).build();
        // ExecutorService executorService = Executors.newFixedThreadPool(40);
        return new ThreadPoolExecutor(
                core * cpuNum,
                max * cpuNum,
                1,
                TimeUnit.MINUTES,
                workQueue,
                threadFactory
        );
    }
}
